﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;

namespace Engine.DynamicObjectManager
{
    public class SceneryObjectPropertiesFile
    {
        #region Private Fields

        private Dictionary<string, BaseObjectProperties> objectProperties;

        #endregion Private Fields

        #region Public Constructors

        public SceneryObjectPropertiesFile()
        {
            this.objectProperties = new Dictionary<string, BaseObjectProperties>();
        }

        #endregion Public Constructors

        #region Public Methods

        public static SceneryObjectPropertiesFile FromFile(string Filename)
        {
            SceneryObjectPropertiesFile file = new SceneryObjectPropertiesFile();
            if (File.Exists(Filename))
            {
                FileStream fs = new FileStream(Filename, FileMode.OpenOrCreate);
                BinaryReader br = new BinaryReader(fs);
                try
                {
                    string header = new string(br.ReadChars(6));
                    if (header != "OBJPRO")
                        throw new Exception("Not correct filetype");

                    switch (br.ReadInt16())
                    {
                        case 1:
                            LoadV1(file, br);
                            break;

                        default:
                            throw new Exception("Wrong fileversion!");
                    }
                }
                catch (Exception e)
                {
                    throw e;
                }

                br.Close();
                fs.Close();
            }
            else
            {
                file.ToFile(Filename);
            }
            return file;
        }

        public void AddObjectPropertie(string moxFilename, BaseObjectProperties properties)
        {
            if (this.objectProperties.ContainsKey(moxFilename))
            {
                this.objectProperties.Remove(moxFilename);
            }

            this.objectProperties.Add(moxFilename, properties);
        }

        public string[] GetAllKnownFallSounds()
        {
            List<string> sounds = new List<string>();

            foreach (KeyValuePair<string, BaseObjectProperties> item in this.objectProperties)
            {
                if (!sounds.Contains(item.Value.FallSound))
                    sounds.Add(item.Value.FallSound);
            }

            return sounds.ToArray();
        }

        public string[] GetAllKnownHitSounds()
        {
            List<string> sounds = new List<string>();

            foreach (KeyValuePair<string, BaseObjectProperties> item in this.objectProperties)
            {
                if (!sounds.Contains(item.Value.CollisionSound))
                    sounds.Add(item.Value.CollisionSound);
            }

            return sounds.ToArray();
        }

        /// <summary>
        /// Return the properties for the given object.
        /// </summary>
        /// <param name="fileName">short filename with extension</param>
        /// <returns></returns>
        public BaseObjectProperties GetPropertie(string fileName)
        {
            BaseObjectProperties prop;
            if (this.objectProperties.TryGetValue(fileName, out prop))
                return prop;
            prop = new BaseObjectProperties(fileName)
            {
                BaseObjectType = EnumBaseObjectType.Static,
                Weight = 1,
                Name = Path.GetFileNameWithoutExtension(fileName),
                FallSound = "",
                CollisionModel = EnumBaseObjectCollisionModel.Self,
                CollisionSound = ""
            };
            MessageBox.Show("Please Create object properties for: \n\n"
                + fileName +
                "\n\nYou can do that in Scenery Editor:\n" +
                "\nExtras => Options => Object Setup");

            return prop;
        }

        public void ToFile(string Filename)
        {
            FileStream fs = new FileStream(Filename, FileMode.Create);
            BinaryWriter bw = new BinaryWriter(fs);

            // Write Header with version number
            bw.Write("OBJPRO".ToCharArray());
            bw.Write((short)1);

            // Write the number of entries
            bw.Write(this.objectProperties.Count);

            // Write the objectproperties
            foreach (KeyValuePair<string, BaseObjectProperties> item in this.objectProperties)
            {
                // write the filename of the mox-file.
                bw.Write(item.Key);
                // write the properties to file.
                item.Value.ToStream(bw);
            }

            bw.Close();
            fs.Close();
        }

        public bool TryToGetValue(string filename, out BaseObjectProperties properties)
        {
            if (this.objectProperties.TryGetValue(filename, out properties))
                return true;
            return false;
        }

        #endregion Public Methods

        #region Private Methods

        private static void LoadV1(SceneryObjectPropertiesFile file, BinaryReader binaryReader)
        {
            int numberOfElements = binaryReader.ReadInt32();
            for (int i = 0; i < numberOfElements; i++)
            {
                file.objectProperties.Add(binaryReader.ReadString(), BaseObjectProperties.FromStream(binaryReader));
            }
        }

        #endregion Private Methods
    }
}